<?php

namespace app\admin\model\shop\delivery;

use app\admin\model\shop\goods\Goods;
use app\shop\library\ShopHelper;
use ba\Exception;
use ba\Tree;
use Psr\SimpleCache\InvalidArgumentException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;
use think\model\relation\BelongsTo;
use think\model\relation\HasMany;
use Throwable;

/**
 * Template
 */
class Template extends Model
{
    // 表名
    protected $name = 'shop_delivery_template';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = true;

    protected $append = ['detail_data'];

    public function detail(): HasMany
    {
        return $this->hasMany(TemplateDetail::class, 'template_id', 'id');
    }

    public function goods(): BelongsTo
    {
        return $this->belongsTo(Goods::class, 'id', 'delivery_template_id');
    }

    public function getDetailDataAttr()
    {
        return $this->detail;
    }

    /**
     * 入库后
     * @param Model $model
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws InvalidArgumentException
     * @throws ModelNotFoundException
     * @throws Throwable
     */
    public static function onAfterWrite(Model $model): void
    {
        self::handleDetail($model->getData('id'), $model->getData('detail_data'));
    }

    /**
     * 删除前
     * @param Model $model
     * @return bool
     * @throws Exception
     */
    public static function onBeforeDelete(Model $model): bool
    {
        if ($model->goods) {
            throw new Exception('该模板已被商品绑定使用，请先解绑后再删除');
        }

        return true;
    }

    /**
     * 删除后
     * @param Model $model
     * @return void
     * @throws DbException
     */
    public static function onAfterDelete(Model $model): void
    {
        $model->detail()->where('template_id', $model->getData('id'))->delete();
    }

    /**
     * 处理模板详情数据
     * @param int   $templateId
     * @param array $detailData
     * @return void
     * @throws Exception
     * @throws Throwable
     */
    public static function handleDetail(int $templateId, array $detailData): void
    {
        // 构造省市数据
        $areaData = ShopHelper::get_all_area();
        $areaData = array_filter($areaData, function ($area) {
            return $area['level'] <= 2;
        });
        $areaData = (new Tree)->assembleChild($areaData);

        $templateDetailData = [];
        foreach ($detailData as $detailKey => &$detail) {
            $cityIdsArr = [];
            $areaIds    = explode('|', $detail['area_id']);
            foreach ($areaIds as $areaId) {
                list($provinceId, $cityId) = explode('-', $areaId);
                // 检查省份数据有效性
                if (!$provinceId) {
                    throw new Exception('添加失败，运费明细省份数据异常');
                }
                if ($cityId == 0) {
                    // 获取省份对应的城市ID
                    $cityIds = array_reduce($areaData, function ($carry, $item) use ($provinceId) {
                        if ($item['id'] == $provinceId) {
                            $carry[] = implode(',', array_column($item['children'], 'id'));
                        }
                        return $carry;
                    }, []);

                    $cityIdsArr = array_merge($cityIdsArr, $cityIds);
                } else {
                    $cityIdsArr[] = $cityId;
                }
            }

            $detail['template_id']    = $templateId;
            $detail['city_id']        = implode(',', $cityIdsArr);
            $detail['template_group'] = implode('-', [$templateId, $detailKey]);

            $templateDetailData[] = $detail;
        }

        $templateDetailModel = new TemplateDetail();
        $templateDetailModel->where('template_id', $templateId)->whereNotIn('id', array_column($detailData, 'id'))->delete();
        $templateDetailModel->saveAll($templateDetailData);
    }
}